home *** CD-ROM | disk | FTP | other *** search
- /* Generic serial line interface routines
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by G1EMM */
- #include "global.h"
- #include "commands.h"
- #include "proc.h"
- #include "iface.h"
- #include "slhc.h"
- #ifdef UNIX
- #include "unixasy.h"
- #else
- #include "n8250.h"
- #endif
- #include "asy.h"
- #include "kiss.h"
- #include "pktdrvr.h"
- #include "ppp.h"
- #include "slip.h"
- #include "nrs.h"
- #include "ctype.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: asy.c,v 1.20 1997/09/07 00:31:16 root Exp root $";
- #endif
-
- int SLIP_MAX = _SLIP_MAX;
- int ASY_MAX = _ASY_MAX;
-
- static int asy_detach (struct iface * ifp);
- extern void pasy (struct asy *asyp);
-
-
- /* Attach a serial interface to the system
- * argv[0]: hardware type, must be "asy"
- * argv[1]: I/O address, e.g., "0x3f8"
- * argv[2]: vector, e.g., "4" In hex, 0x prefix optional.
- * argv[3]: mode, may be:
- * "slip" (point-to-point SLIP)
- * "ax25" (AX.25 frame format in SLIP for raw TNC)
- * "nrs" (NET/ROM format serial protocol)
- * "ppp" (Point-to-Point Protocol, RFC1171, RFC1172)
- * "pkiss" (Polled KISS ala G8BPQ)
- * argv[4]: interface label, e.g., "sl0"
- * argv[5]: receiver ring buffer size in bytes
- * argv[6]: maximum transmission unit, bytes
- * argv[7]: interface speed, e.g, "9600"
- * argv[8]: optional flags,
- * 'c' BPQ-style checksum used in kiss mode - WG7J
- * 'v' for Van Jacobson TCP header compression (SLIP only,
- * use ppp command for VJ compression with PPP);
- * 'f' for forced use of the 16550 fifo's - WG7J
- * 'dd' to set 16550 trigger level to 'dd' (an integer) - WG7J
- * 't' to display pkiss outbound polling on trace display
- * (supressed by default)
- */
- int
- asy_attach (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct iface *ifp;
- struct asy *asyp;
- char *ifn;
- int dev;
- int xdev;
- int trigchar = -1;
- char monitor = FALSE;
- int polled = 0;
- int triglevel = 0;
- int force = 0;
- char *cp;
- #if defined(SLIP) || defined(AX25)
- struct slip *sp = (struct slip *)0;
- #endif
- #ifdef NRS
- struct nrs *np = (struct nrs *)0;
- #endif
-
- if (if_lookup (argv[4]) != NULLIF) {
- tprintf (Existingiface, argv[4]);
- return -1;
- }
- /* Find unused asy control block */
- for (dev = 0; dev < ASY_MAX; dev++) {
- asyp = &Asy[dev];
- if (asyp->iface == NULLIF)
- break;
- }
- if (dev >= ASY_MAX) {
- tputs ("Too many async controllers\n");
- return -1;
- }
-
- /* Create interface structure and fill in details */
- ifp = (struct iface *) callocw (1, sizeof (struct iface));
-
- ifp->addr = Ip_addr;
- ifp->name = strdup (argv[4]);
- ifp->iface_metric = 1;
- ifp->mtu = (int16) atoi (argv[6]);
- ifp->dev = dev;
- ifp->stop = asy_detach;
-
- /*Check for forced 16550 fifo usage - WG7J */
- if ((argc > 8) && ((cp = strchr (argv[8], 'f')) != NULLCHAR)) {
- force = 1;
- if ((triglevel = atoi (++cp)) == 0) /* is there an additional arg ? */
- if (argc > 9)
- triglevel = atoi (argv[9]);
- }
- #ifdef SLIP
- if (stricmp (argv[3], "SLIP") == 0) {
- for (xdev = 0; xdev < SLIP_MAX; xdev++) {
- sp = &Slip[xdev];
- if (sp->iface == NULLIF)
- break;
- }
- if (!sp || xdev >= SLIP_MAX) {
- tputs ("Too many slip devices\n");
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
- (void) setencap (ifp, "SLIP");
- ifp->ioctl = asy_ioctl;
- ifp->raw = slip_raw;
- ifp->show = slip_status;
- ifp->flags = 0;
- ifp->xdev = xdev;
-
- sp->iface = ifp;
- sp->send = asy_send;
- sp->get = get_asy;
- sp->type = CL_SERIAL_LINE;
- trigchar = FR_END;
- #ifdef VJCOMPRESS
- if ((argc > 8) && (strchr (argv[8], 'v') != NULLCHAR)) {
- sp->escaped |= SLIP_VJCOMPR;
- sp->slcomp = slhc_init (16, 16);
- }
- #else
- sp->slcomp = NULL;
- #endif /* VJCOMPRESS */
- ifp->rxproc = newproc (ifn = if_name (ifp, " rx"), 256, asy_rx, xdev, NULL, NULL, 0);
- free (ifn);
- } else
- #endif
- #ifdef AX25
- if (stricmp (argv[3], "AX25") == 0
- #ifdef POLLEDKISS
- || stricmp (argv[3], "PKISS") == 0
- #endif
- ) {
- /* Set up a SLIP link to use AX.25 */
- for (xdev = 0; xdev < SLIP_MAX; xdev++) {
- sp = &Slip[xdev];
- if (sp->iface == NULLIF)
- break;
- }
- if (!sp || xdev >= SLIP_MAX) {
- tputs ("Too many ax25"
- #ifdef POLLEDKISS
- "or pkiss"
- #endif
- " devices\n");
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
- (void) setencap (ifp, "AX25");
- #ifdef KISS
- ifp->ioctl = kiss_ioctl;
- ifp->raw = kiss_raw;
- #endif
- ifp->show = slip_status;
- ifp->port = 0; /* G1EMM */
- if (ifp->hwaddr == NULLCHAR)
- ifp->hwaddr = mallocw (AXALEN);
- memcpy (ifp->hwaddr, Mycall, AXALEN);
- if (ifp->ipcall == NULLCHAR)
- ifp->ipcall = mallocw (AXALEN);
- memcpy (ifp->ipcall, Mycall, AXALEN);
- ifp->xdev = xdev;
-
- sp->iface = ifp;
- sp->send = asy_send;
- sp->kiss[ifp->port] = ifp; /* G1EMM */
- sp->get = get_asy;
- sp->type = CL_KISS;
- sp->polled = sp->usecrc = sp->tracepoll = 0;
- trigchar = FR_END;
- ifp->rxproc = newproc (ifn = if_name (ifp, " rx"), 256, asy_rx, xdev, NULL, NULL, 0);
- #ifdef POLLEDKISS
- if (toupper (*argv[3]) == 'P') {
- polled = 1;
- sp->polled = sp->usecrc = 1; /* PKISS => usecrc (for compatibility) */
- if ((argc > 8) && strchr (argv[8], 't') != NULLCHAR)
- sp->tracepoll = 1;
- }
- if ((argc > 8) && (strchr (argv[8], 'c') != NULLCHAR))
- sp->usecrc = 1;
- #endif
- free (ifn);
- } else
- #endif
- #ifdef NRS
- if (stricmp (argv[3], "NRS") == 0) {
- /* Set up a net/rom serial iface */
- for (xdev = 0; xdev < SLIP_MAX; xdev++) {
- np = &Nrs[xdev];
- if (np->iface == NULLIF)
- break;
- }
- if (!np || xdev >= SLIP_MAX) {
- tputs ("Too many nrs devices\n");
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
- /* no call supplied? */
- (void) setencap (ifp, "AX25");
- ifp->ioctl = asy_ioctl;
- ifp->raw = nrs_raw;
- /* ifp->show = nrs_status; */
- ifp->hwaddr = mallocw (AXALEN);
- memcpy (ifp->hwaddr, Mycall, AXALEN);
- ifp->ipcall = mallocw (AXALEN);
- memcpy (ifp->ipcall, Mycall, AXALEN);
- ifp->xdev = xdev;
- np->iface = ifp;
- np->send = asy_send;
- np->get = get_asy;
- trigchar = ETX;
- ifp->rxproc = newproc (ifn = if_name (ifp, " nrs"), 256, nrs_recv, xdev, NULL, NULL, 0);
- free (ifn);
- } else
- #endif
- #ifdef PPP
- if (stricmp (argv[3], "PPP") == 0) {
- /* Setup for Point-to-Point Protocol */
- trigchar = HDLC_FLAG;
- monitor = TRUE;
- (void) setencap (ifp, "PPP");
- ifp->ioctl = asy_ioctl;
- ifp->flags = FALSE;
- /* Initialize parameters for various PPP phases/protocols */
- if (ppp_init (ifp) != 0) {
- tputs ("Cannot allocate PPP control block\n");
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
- } else
- #endif /* PPP */
- {
- tprintf ("Mode %s unknown for interface %s\n", argv[3], argv[4]);
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
-
- /* Link in the interface */
- ifp->next = Ifaces;
- Ifaces = ifp;
- #ifdef UNIX
- /* *ix version can fail (e.g. "device locked"). Detach if it does. */
- if (asy_init (dev, ifp, argv[1], argv[2], (int16) atol (argv[5]),
- trigchar, monitor, (int16) atol (argv[7]), force, triglevel, polled) == -1)
- (void) if_detach (ifp);
- #else
- (void) asy_init (dev, ifp, argv[1], argv[2], (int16) atol (argv[5]),
- trigchar, monitor, (int16) atol (argv[7]), force, triglevel, polled);
- #endif
- return 0;
- }
-
-
- static int
- asy_detach (ifp)
- struct iface *ifp;
- {
- (void) asy_stop (ifp);
-
- #ifdef SLIP
- if (stricmp (ifp->iftype->name, "SLIP") == 0) {
- Slip[ifp->xdev].iface = NULLIF;
- #ifdef VJCOMPRESS
- slhc_free (Slip[ifp->xdev].slcomp);
- Slip[ifp->xdev].slcomp = NULL;
- #endif /* VJCOMPRESS */
- } else
- #endif
- #ifdef AX25
- if (stricmp (ifp->iftype->name, "AX25") == 0 && Slip[ifp->xdev].iface == ifp)
- Slip[ifp->xdev].iface = NULLIF;
- else
- #endif
- #ifdef NRS
- if (stricmp (ifp->iftype->name, "AX25") == 0 && Nrs[ifp->xdev].iface == ifp)
- Nrs[ifp->xdev].iface = NULLIF;
- else
- #endif
- #ifdef PPP
- if (stricmp (ifp->iftype->name, "PPP") == 0)
- (void) ppp_free (ifp);
- else
- #endif
- {
- tprintf ("invalid type %s for interface %s\n", ifp->iftype->name, ifp->name);
- free (ifp->name);
- free (ifp);
- return -1;
- }
- return 0;
- }
-
-
- /* Execute user comm command */
- int
- doasycomm (argc, argv, p)
- int argc OPTIONAL;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct iface *ifp;
- register struct asy *ap;
- int dev;
- struct mbuf *bp;
-
- if ((ifp = if_lookup (argv[1])) == NULLIF) {
- tprintf (Badinterface, argv[1]);
- return 1;
- }
- for (dev = 0, ap = Asy; dev < ASY_MAX; dev++, ap++)
- if (ap->iface == ifp)
- break;
- if (dev == ASY_MAX) {
- tprintf ("Interface %s not asy port\n", argv[1]);
- return 1;
- }
- bp = pushdown (NULLBUF, (int16) strlen (argv[2]) + 2);
- strncpy ((char *)bp->data, argv[2], strlen(argv[2]) + 1);
- strcat ((char *)bp->data, "\r");
- bp->cnt = (int16) (strlen (argv[2]) + 1);
- (void) asy_send (dev, bp);
- return 0;
- }
-
-
- int
- doasystat (int argc, char **argv, void *p OPTIONAL)
- {
- register struct asy *asyp;
- struct iface *ifp;
- int i;
- int k;
-
- if (argc < 2) {
- for (k = 0, asyp = Asy; k < ASY_MAX; k++, asyp++) {
- if (asyp->iface != NULLIF)
- pasy (asyp);
- }
- return 0;
- }
- for (i = 1; i < argc; i++) {
- if ((ifp = if_lookup (argv[i])) == NULLIF) {
- tprintf ("Interface %s unknown\n", argv[i]);
- continue;
- }
- for (k = 0, asyp = Asy; k < ASY_MAX; k++, asyp++) {
- if (asyp->iface == ifp) {
- pasy (asyp);
- break;
- }
- }
- if (k == ASY_MAX || !asyp)
- tprintf ("Interface %s not asy\n", argv[i]);
- }
-
- return 0;
- }
-
-
-
- #ifdef KISS
-
- /* Attach a pseudo ax25 interface to the system, for local loopback of ax25
- *
- */
- int axloop_attach (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- register struct iface *ifp;
- int xdev;
- struct slip *sp = (struct slip *)0;
-
- if (if_lookup ("axlp") != NULLIF) {
- tprintf (Existingiface, "axlp");
- return -1;
- }
-
- /* Create interface structure and fill in details */
- ifp = (struct iface *) callocw (1, sizeof (struct iface));
-
- ifp->addr = Ip_addr;
- ifp->name = strdup ("axlp");
- ifp->iface_metric = 1;
- ifp->mtu = 1500;
- ifp->dev = 0;
- ifp->flags = LOOPBACK_AX25;
- ifp->stop = asy_detach;
-
-
- /* Set up a SLIP link to use AX.25 */
- for (xdev = 0; xdev < SLIP_MAX; xdev++) {
- sp = &Slip[xdev];
- if (sp->iface == NULLIF)
- break;
- }
- if (!sp || xdev >= SLIP_MAX) {
- tputs ("Too many ax25"
- #ifdef POLLEDKISS
- "or pkiss"
- #endif
- " devices\n");
- free (ifp->name);
- free ((char *) ifp);
- return -1;
- }
-
- (void) setencap (ifp, "AX25");
- ifp->ioctl = kiss_ioctl;
- ifp->raw = kiss_raw;
-
- ifp->show = slip_status;
- ifp->port = 0; /* G1EMM */
- if (ifp->hwaddr == NULLCHAR)
- ifp->hwaddr = mallocw (AXALEN);
- memcpy (ifp->hwaddr, Mycall, AXALEN);
- if (ifp->ipcall == NULLCHAR)
- ifp->ipcall = mallocw (AXALEN);
- memcpy (ifp->ipcall, Mycall, AXALEN);
- ifp->xdev = xdev;
-
- sp->iface = ifp;
- sp->send = asy_send;
- sp->kiss[ifp->port] = ifp; /* G1EMM */
- sp->get = get_asy;
- sp->type = CL_KISS;
- sp->polled = sp->usecrc = sp->tracepoll = 0;
-
- ifp->next = Ifaces;
- Ifaces = ifp;
- return 0;
- }
- #endif
-
-